﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xos_http.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../impl/head.h"
#include "session.h"

namespace xos_http
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    typedef xos_stl::auto_map< std::string, session, thread_lock > SESSION_MAP;
    typedef SESSION_MAP::iterator SESSION_ITER;

    static session::POOL * pool_ptr = 0;
    static SESSION_MAP * map_ptr = 0;

    // session存活时间
    static int n_session_timeout_ms = 1000 * 600;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    session::session()
    {
        init_data();
    }

    session::~session()
    {}

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // public method

    int session::get_addr( POOL *** pppPool, LIST *** pppList )
    {
        int ret = 0;
        if( pppPool )
        {
            *pppPool = &pool_ptr;
        }
        if( pppList )
        {
            *pppList = 0;
        }
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    session * session::get( const char * lpszId )
    {
        session * pRet = 0;

        xos::i_misc * pMisc = mgr::container()->misc();
        SESSION_MAP & mp = *map_ptr;
        char guid[64] = { 0 };

        if( lpszId )
        {
            mp.lock();
            SESSION_ITER iter = mp.find( lpszId );
            if( iter != mp.end() )
            {
                pRet = iter->second;
            }
            mp.un_lock();
        }
        else
        {
            pMisc->create_guid( guid );
            lpszId = guid;
        }

        if( !pRet )
        {
            xos_stl::init_pool_item( pRet, true );
            pRet->m_id = lpszId;
            mp.lock();
            mp[pRet->m_id] = pRet;
            mp.un_lock();
        }

        {
            f_session fun = mgr::get()->session_callback( 0 );
            if( fun )
            {
                fun( pRet, true );
            }
        }

        return pRet;
    }

    int session::remove( session *& pSession )
    {
        int ret = 0;

        SESSION_MAP & mp = *map_ptr;

        mp.lock();
        {
            mp.erase( pSession->m_id );
        }
        mp.un_lock();

        return ret;
    }

    int session::heart( int interval_ms )
    {
        int ret = 0;

        SESSION_MAP & mp = *map_ptr;

        mp.lock();
        for( SESSION_ITER iter = mp.begin(); iter != mp.end(); )
        {
            SESSION_ITER old_iter = iter++;
            session * pS = old_iter->second;
            pS->m_nTimeToTimeout_ms -= interval_ms;
            if( pS->m_nTimeToTimeout_ms > 0 )
            {
                continue;
            }
            xos_stl::release_interface( pS );
            mp.erase( old_iter );
        }
        mp.un_lock();

        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int session::static_user_init()
    {
        int ret = 0;

        if( 0 == ret )
        {
            xos_stl::init_map( map_ptr );
        }

        return ret;
    }

    int session::static_user_term()
    {
        int ret = 0;

        xos_stl::term_map( map_ptr, true );

        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int session::init_data()
    {
        int ret = 0;

        reset_timeout();
        m_id = "";

        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int session::reset_timeout()
    {
        int ret = 0;
        m_nTimeToTimeout_ms = n_session_timeout_ms;
        return ret;
    }

    int session::init()
    {
        int ret = 0;
        return ret;
    }

    int session::term()
    {
        int ret = 0;

        {
            f_session fun = mgr::get()->session_callback( 0 );
            if( fun )
            {
                fun( this, false );
            }
        }

        init_data();

        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // i_session method
    // 

    const char * session::id( const char * lpszId )
    {
        const char * lpStr = lpszId;
        std::string & str = m_id;
        if( lpStr )
        {
            str = lpStr;
        }
        return str.c_str();
    }

} // xos_http
